//
//  BlenderLayer.cpp
//  slushy
//
//  Created by luotianqiang1 on 17/5/27.
//
//

#include "BlenderLayer.h"
#include "FoodData.h"
#include "TouchNodeComponent.h"
#include "particleLayer.h"
#include "FallLayer.h"
IMPLEMENT_COCOS2DX_CLASS(BlenderLayer);
REGIST_SECENE(BlenderLayer)
const int blendSoundActionTag = 10101;
bool BlenderLayer::init(){
    if(BaseMakeLayer::init()) {
        _operate = StudioLayer::create("BlenderLayer.csb");
        addChild(_operate);
        _prompt = _operate->getNodeByName<Sprite*>("finger");
        vector<string> hideNodes = {"cola","ice","blender","lid","fruit","water"};
        for(auto name:hideNodes)
            _operate->getNodeByName(name)->setVisible(false);
        addThings = FoodData::getFallThings();
        colorNames = FoodData::getColorNames();
        _operate->getNodeByName<ui::Widget*>("btn")->setEnabled(false);
        return true;
    }
    return false;
}

void BlenderLayer::touchEnd(ui::Widget* widget){
    if(widget->getName() == "btn"){
        
    }
}


void BlenderLayer::onEnterTransitionDidFinish(){
    BaseMakeLayer::onEnterTransitionDidFinish();
    SoundPlayer::getInstance()->playEffect("sound/general/ingredients_fly_in.mp3");
    changeNodeToClipping({"colaInner"});
    getScene()->getPhysicsWorld()->setGravity(Vec2(0.0f, -250));
    getScene()->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_NONE);
    Device::setAccelerometerEnabled(true);
    getScene()->getPhysicsWorld()->setUpdateRate(0.5f);
    auto blender = _operate->getNodeByName("blender");
    Vec2 verts[] = {
        Vec2(-145.5f-200, 150.6f+200),
        Vec2(-145.5f, 150.6f),
        Vec2(-117.1f, -97.6f),
        Vec2(-56.2f, -129.7f),
        Vec2(6.1f, -113.4f),
        Vec2(32.8f, -112.3f),
        Vec2(72.1f, 149.2f),
        Vec2(72.1f+200, 149.2f+280)
    };
    auto cup = _operate->getNodeByName("cup");
    auto blenderEdgeChain =  PhysicsBody::createEdgeChain(&verts[0], sizeof(verts)/sizeof(*verts));
    blenderEdgeChain->setCategoryBitmask(0x38);//0011 1000
    blenderEdgeChain->setCollisionBitmask(0x38);
    blenderEdgeChain->setGroup(-1);
    auto node1 = Node::create();
    node1->setPhysicsBody(blenderEdgeChain);
    node1->setPosition(cup->getContentSize()*.5);
    cup->addChild(node1);
    ActionHelper::showBackInOut(blender, blender->getPosition(), ActionHelper::ShowDirection::show_from_left,[=](){
        auto cupUp = _operate->getNodeByName("cupUp");
        cupUp->setLocalZOrder(4);
        CocosHelper::reAddNode(cupUp, blender->getParent());
    },0.9f);
    blender->setVisible(true);
    
    
    ActionHelper::delayFunc(0.9f, this, [=](){
        auto itor = addThings.begin();
        if(itor != addThings.end()){
            showFallThing(*itor);
            addThings.erase(itor);
        }
    });
    
}

void BlenderLayer::showFallThing(string name){
    SoundPlayer::getInstance()->playEffect("sound/general/ingredients_fly_in.mp3");
    auto ice = _operate->getNodeByName(name);
    if(name == "fruit" || name == "ice") {
        Vec2 verts[] = {
            Vec2(-150.3f, 39.7f),
            Vec2(-99.9f, -57.2f),
            Vec2(-32.1f, -96.8f),
            Vec2(55.0f, -88.3f),
            Vec2(122.9f, -47.3f),
            Vec2(165.1f, 67.6f)
        };
        
        
        if(name == "fruit") {
            auto tempNode = StudioLayer::createNoLayout("fallFruit/"+FoodData::getFlavor() +".csb");
            auto tempBowl = tempNode->getNodeByName("bowl");
            if(tempBowl) {
                auto chids = Vector<Node*>(tempBowl->getChildren());
                for(auto child:chids){
                    child->retain();
                    child->removeFromParent();
                    ice->addChild(child);
                    child->release();
                }
            }
        }
        
        vector<int> CategoryBitmask = {0x01,0x02,0x04};//{0001,0010,0100}
        auto chids = ice->getChildren();
        int i=0;
        for(auto food:chids){
            if(food->getName()!= "noshade" && food->getName() != name+ "BowlUp"&& food->getName() != "Audio"){
                auto size = food->getContentSize();
                PhysicsBody* box;
                if(name == "fruit"){
                    // box = PhysicsBody::createCircle(size.height*0.3f);
                    box = PhysicsBody::createBox(Size(size.width*0.7,size.height*0.7));
                  
                }
                else{
                    box = PhysicsBody::createCircle(size.width*0.3f);
                    ice0.push_back(food);
                }
                box->setCategoryBitmask(CategoryBitmask[0]);
                box->setCollisionBitmask(CategoryBitmask[0]);
                box->setRotationOffset(food->getRotationX());
                food->setPhysicsBody(box);
                food->setName(StringUtils::format("%s%d",name.c_str(),i));
                food->getParent()->reorderChild(food, rand()%5+1);
                i++;
            }
        }
        auto iceBowlUp = _operate->getNodeByName(name +"BowlUp");
        iceBowlUp->getParent()->reorderChild(iceBowlUp, 6);
        
        
        auto bowlEdgeChain =  PhysicsBody::createEdgeChain(&verts[0], sizeof(verts)/sizeof(*verts));
        bowlEdgeChain->setCategoryBitmask(CategoryBitmask[0]);
        bowlEdgeChain->setCollisionBitmask(CategoryBitmask[0]);
        bowlEdgeChain->setGroup(-1);
        
        auto node = Node::create();
        node->setPhysicsBody(bowlEdgeChain);
        node->setPosition(ice->getContentSize()*.5);
        ice->addChild(node);
    }
    ActionHelper::showBezier(ice, ice->getPosition(), ActionHelper::ShowDirection::show_from_right,[=](){
        auto drag = createDraOperate(ice);
        drag->setNeedGravity(true);
        if(ice->getName() == "ice")
            ActionHelper::runBezierMoveHideAction(_prompt, _operate->getPosinWord(ice->getName()),  _operate->getPosinWord("limit"));
    },0.9f);
    ice->setVisible(true);
    
}

void BlenderLayer::showColor(string colorName){
    SoundPlayer::getInstance()->playEffect("sound/general/ingredients_fly_in.mp3");
    auto node =  CocosHelper::findNode_if(_operate, [](Node* node){
        return  node->getName().find("color") != string::npos;
    });
    if(node){
        auto noshade = dynamic_cast<Sprite*>(node->getChildByName("noshade"));
        noshade->setTexture("PNG/4/"+colorName+".png");
        auto particle = dynamic_cast<ParticleSystemQuad*>(node->getChildByName("particle"));
        particle->setTexture(Director::getInstance()->getTextureCache()->addImage("PNG/4/coloring_"+colorName+"1.png"));
        ActionHelper::showBezier(node, node->getPosition(), ActionHelper::ShowDirection::show_from_right,[=](){
            auto drag = createDraOperate(node);
            drag->setNeedGravity(true);
        },0.9f);
        node->setVisible(true);
    }
    
}

void BlenderLayer::startFall(LQComponent* lc, OperateListner* _lis){
    BaseMakeLayer::startFall(lc, _lis);
    auto bowl = lc->getOwner();
    bowl->getParent()->reorderChild(bowl, 0);
    auto cup = _operate->getNodeByName("cup");
    auto cupUp = _operate->getNodeByName("cupUp");
    if(bowl->getName() == "fruit"|| bowl->getName() == "ice") {
        auto chids = bowl->getChildren();
        CocosHelper::reAddNode(bowl, cup);
        auto bowlUp = _operate->getNodeByName(bowl->getName()+"BowlUp");
        bowlUp->setLocalZOrder(-1);
        CocosHelper::reAddNode(bowlUp, cupUp);
        bowlUp->setRotation(bowl->getRotation());
        bowl->runAction(RotateTo::create(0.8f, -100));
        bowlUp->runAction(RotateTo::create(0.8f, -100));
        for(auto food:chids){
            auto physic =  food->getPhysicsBody();
            if(physic){
                auto bitMask = physic->getCategoryBitmask();
                bitMask = bitMask<<3;
                physic->setCategoryBitmask(bitMask);
                physic->setCollisionBitmask(bitMask);
                if(food->getName().find(bowl->getName()) != string::npos){
                    CocosHelper::reAddNode(food, cup);
                }
                if(food->getName().find("ice") == string::npos) {
                    physic->setGroup(-2);
                    food->runAction(Sequence::create(FadeOut::create(5),CallFunc::create([=](){
                        actionNodes.erase(std::find(actionNodes.begin(), actionNodes.end(), food));
                        food->removeFromParent();
                    }), nullptr));
                    _actionManager->pauseTarget(food);
                    actionNodes.push_back(food);
                }
            }
        }
        ActionHelper::delayFunc(2.7, lc->getOwner(), [lc](){
            lc->dispatcherEvent(FallThingfallEnd);
        });
    }else if(bowl->getName() == "cola") {
        auto paths = {"PNG/5/Slushy_animation/cola3_.png","PNG/5/Slushy_animation/cola3.png"};
        int i=0;
        for(auto path:paths){
            auto clip = ClippingNode::create();
            clip->setLocalZOrder(7*i);
            clip->setAlphaThreshold(0.01f);
            cup->addChild(clip);
            auto mask = Sprite::create("PNG/5/blender_cup_mask.png");
            mask->setPosition(cup->getContentSize()*.5);
            clip->setStencil(mask);
            auto node = Sprite::create(path);
            node->setCascadeOpacityEnabled(true);
            node->setPosition(137.51,-160);
            clip->addChild(node);
            node->runAction(Sequence::create(DelayTime::create(1.2f), MoveTo::create(3, Vec2(137.51,30)),CallFunc::create([=](){
                if(i==0)
                    lc->dispatcherEvent(FallThingfallEnd);
                node->runAction(FadeOut::create(12));
                _actionManager->pauseTarget(node);
                actionNodes.push_back(node);
            }), nullptr));
            i++;
        }
    }else if(bowl->getName().find("color") != string::npos){
        auto inCup = Sprite::create("PNG/4/"+currentColor+"1.png");
        inCup->setPosition(122.57-35 +rand()%70,170-rand()%25+8);
        cup->addChild(inCup,6);
        inCup->setOpacity(0);
        inCup->runAction(Sequence::create(FadeIn::create(1.2f),CallFunc::create([=](){
            lc->dispatcherEvent(FallThingfallEnd);
            inCup->runAction(FadeOut::create(5));
            _actionManager->pauseTarget(inCup);
            actionNodes.push_back(inCup);
        }), nullptr));
    }else if(bowl->getName()=="water") {
        auto paths = {"PNG/5/w_.png","PNG/5/w.png"};
        int i=0;
        for(auto path:paths){
            auto clip = ClippingNode::create();
            clip->setLocalZOrder(7*i);
            clip->setAlphaThreshold(0.01f);
            cup->addChild(clip);
            auto mask = Sprite::create("PNG/5/blender_cup_mask.png");
            mask->setPosition(cup->getContentSize()*.5);
            clip->setStencil(mask);
            auto node = Sprite::create(path);
            node->setCascadeOpacityEnabled(true);
            node->setPosition(137.51,-160);
            clip->addChild(node);
            node->runAction(Sequence::create(DelayTime::create(1.2f), MoveTo::create(3, Vec2(137.51,30)),CallFunc::create([=](){
                if(i==0)
                    lc->dispatcherEvent(FallThingfallEnd);
                node->runAction(FadeOut::create(12));
                _actionManager->pauseTarget(node);
                actionNodes.push_back(node);
            }), nullptr));
            i++;
        }
    }
}
void BlenderLayer::fallEnd(LQComponent* fall, OperateListner* _lis){
    BaseMakeLayer::fallEnd(fall, _lis);
    auto bowlUp = _operate->getNodeByName(fall->getOwner()->getName()+"BowlUp");
    if(bowlUp){
        bowlUp->setLocalZOrder(0);
        CocosHelper::reAddNode(bowlUp, fall->getOwner());
        bowlUp->setRotation(0);
    }
    
    ActionHelper::delayFunc(0.9f, this, [=](){
        fall->getOwner()->getParent()->reorderChild(fall->getOwner(), 40);
        fall->getOwner()->runAction(RotateTo::create(0.4, 0));
        ActionHelper::hide(fall->getOwner(), ActionHelper::ShowDirection::show_from_right,[=](){
            fall->getOwner()->removeFromParent();
            auto itor = addThings.begin();
            if(itor != addThings.end()){
                auto nodeName = *itor;
                if(nodeName== "color"){
                    currentColor = *colorNames.begin();
                    showColor(currentColor);
                    colorNames.erase(colorNames.begin());
                    if(colorNames.size() == 0)
                        addThings.erase(itor);
                }else {
                    showFallThing(*itor);
                    addThings.erase(itor);
                }
                
            }else {
                showLid();
            }
        },false);
    });
}

void BlenderLayer::showLid(){
    SoundPlayer::getInstance()->playEffect("sound/general/ingredients_fly_in.mp3");
    auto cupUp = _operate->getNodeByName("cupUp");
    cupUp->setLocalZOrder(4);
    CocosHelper::reAddNode(cupUp, _operate->getNodeByName("blender"));
    auto lid = _operate->getNodeByName("lid");
    lid->setVisible(true);
    ActionHelper::show(lid, lid->getPosition(), ActionHelper::ShowDirection::show_from_right,[=](){
        auto touchMove = TouchMoveComponent::create();
        lid->addComponent(touchMove);
        touchMove->setMoveType(MoveComponentType::kTypeBack);
        touchMove->setTarget(LQRect::create(CocosHelper::getNodeRectInWorld(_operate->getNodeByName("limit"))));
        ActionHelper::runBezierMoveHideAction(_prompt, _operate->getPosinWord(lid->getName()),  _operate->getPosinWord("limit"));
        touchMove->setBrintTop(true);
        touchMove->addListners(ComponentTouchEnd, [=](LQComponent*,OperateListner*){
            this->stopPrompt();
            auto f = FrameStatus::create(lid->getName());
            f->setSearchAction(_operate->getAction());
            auto endPos = f->searchPostion("pouring");
            f->remove();
            lid->runAction(Sequence::create(JumpTo::create(0.8f, endPos, 100, 1),CallFunc::create([this](){
                auto blender = _operate->getNodeByName("blender");
                blender->runAction(Sequence::create(JumpTo::create(0.8f, Vec2(320,blender->getPositionY()+70), 50, 1),CallFunc::create([this](){
                    auto btn = _operate->getNodeByName<ui::Widget*>("btn");
                    btn->setEnabled(true);
                    _prompt->setPosition(_operate->getPosinWord("btn")-Vec2(0,40));
                    _prompt->setVisible(true);
                    _prompt->runAction(ActionHelper::createUpDownPrompt());
                    auto touchNode = TouchNodeComponent::create();
                    touchNode->setSwallowTouches(false);
                    btn->addComponent(touchNode);
                    touchNode->addListners(ComponentTouchBegan, CC_CALLBACK_2(BlenderLayer::touchDown, this));
                    touchNode->addListners(ComponentTouchEnd, CC_CALLBACK_2(BlenderLayer::touchUp, this));
                    touchNode->addListners(ComponentTouchCancle, CC_CALLBACK_2(BlenderLayer::touchUp, this));
                    
                    auto cup = _operate->getNodeByName("cup");
                    auto mixPath = FoodData::getMixPath();
                    auto clip = ClippingNode::create();
                    clip->setLocalZOrder(7);
                    clip->setAlphaThreshold(0.01f);
                    cup->addChild(clip);
                    auto mask = Sprite::create("PNG/5/blender_cup_mask.png");
                    mask->setPosition(cup->getContentSize()*.5);
                    clip->setStencil(mask);
                  
                    
                    auto mixEnd = Sprite::create(mixPath[0]);
                    mixEnd->setPosition(137.51,-160);
                    clip->addChild(mixEnd);
                    mixEnd->setOpacity(0);
                    mixEnd->runAction(FadeIn::create(10));
                    mixEnd->runAction(Sequence::create(MoveBy::create(12, Vec2(0,240)),CallFunc::create(CC_CALLBACK_0(BlenderLayer::blendAllEnd, this)), nullptr));
                    _actionManager->pauseTarget(mixEnd);
                    actionNodes.push_back(mixEnd);
                    
                    if(mixPath.size()>1){
                        auto fruit0 = Sprite::create(mixPath[1]);
                        fruit0->setPosition(137.51-fruit0->getContentSize().width,-40-40);
                        clip->addChild(fruit0,1);
                        fruit0->setOpacity(0);
                        fruit0->runAction(Sequence::create(FadeIn::create(2),DelayTime::create(9),FadeOut::create(1), nullptr));
                        fruit0->runAction(RepeatForever::create(Sequence::create(MoveBy::create(1.4f, Vec2(fruit0->getContentSize().width*2,0)),MoveBy::create(0, Vec2(-fruit0->getContentSize().width*2,0)), nullptr)));
                        fruit0->runAction(MoveBy::create(12, Vec2(0,120)));
                        _actionManager->pauseTarget(fruit0);
                        actionNodes.push_back(fruit0);
                        
                        auto fruit1 = Sprite::create(mixPath[1]);
                        fruit1->setPosition(137.51,-40-40);
                        clip->addChild(fruit1,1);
                        fruit1->setOpacity(0);
                        fruit1->runAction(Sequence::create(MoveBy::create(0.7f, Vec2(fruit0->getContentSize().width,0)),CallFunc::create([=](){
                            fruit1->runAction(RepeatForever::create(Sequence::create(MoveBy::create(0, Vec2(-fruit0->getContentSize().width*2,0)), MoveBy::create(1.4f, Vec2(fruit0->getContentSize().width*2,0)),nullptr)));
                        }), nullptr));
                        fruit1->runAction(Sequence::create(FadeIn::create(2),DelayTime::create(9),FadeOut::create(1), nullptr));
                        fruit1->runAction(MoveBy::create(12, Vec2(0,120)));
                        _actionManager->pauseTarget(fruit1);
                        actionNodes.push_back(fruit1);
                    }
                    
                    
                }), nullptr));
                SoundPlayer::getInstance()->playEffect("sound/general/ingredients_fly_in.mp3");
            }), nullptr));
            ActionHelper::delayFunc(0.6, this, [=](){
                lid->getParent()->reorderChild(lid, 1);
                touchMove->playSound();
            });
        });
    });
    
}

void BlenderLayer::touchDown(LQComponent* fall, OperateListner* _lis){
     this->stopActionByTag(blendSoundActionTag);
    fall->getOwner()->stopAllActions();
    this->stopPrompt();
    this->schedule(schedule_selector(BlenderLayer::blendIce), 0.4f);
    if(_loopSound == -1)
    _loopSound = SoundPlayer::getInstance()->playEffectLoop("sound/Food blender running.mp3");
    for(auto node:actionNodes)
        _actionManager->resumeTarget(node);
}
void BlenderLayer::touchUp(LQComponent* fall, OperateListner* _lis){
    this->unschedule(schedule_selector(BlenderLayer::blendIce));
     this->stopActionByTag(blendSoundActionTag);
    auto action = Sequence::create(DelayTime::create(1), CallFunc::create([=](){
        this->stopPrompt();
        SoundPlayer::getInstance()->stopEffectLoop(_loopSound);
        _loopSound = -1;
        _prompt->setPosition(_operate->getPosinWord("btn")-Vec2(0,40));
        _prompt->setVisible(true);
        _prompt->runAction(ActionHelper::createUpDownPrompt());
    }),nullptr);
    action->setTag(blendSoundActionTag);
    this->runAction(action);
    for(auto node:actionNodes)
        _actionManager->pauseTarget(node);
}

void BlenderLayer::blendIce(float time){
    auto size = ice0.size();
    if(size>0){
        auto index = rand()%size;
        auto node = ice0[index];
        ice0.erase(ice0.begin()+index);
        auto icePysic = node->getPhysicsBody();
        for(int i=0;i<2;i++){
            auto newIce = Sprite::create(StringUtils::format("PNG/5/5/2_%d.png",i));
            ice1.push_back(newIce);
            newIce->setPosition(node->getPosition());
            newIce->setRotation(newIce->getRotationX());
            node->getParent()->addChild(newIce,node->getLocalZOrder());
            
            PhysicsBody* box = PhysicsBody::createCircle(newIce->getContentSize().width*0.25f);
            box->setCategoryBitmask(icePysic->getCategoryBitmask());
            box->setCollisionBitmask(icePysic->getCollisionBitmask());
            box->setRotationOffset(newIce->getRotationX());
            newIce->setPhysicsBody(box);
        }
        node->removeFromParent();
    }
    
    size = ice1.size();
    if(size>0&&ice0.size()==0){
        auto index = rand()%size;
        auto node = ice1[index];
        ice1.erase(ice1.begin()+index);
        auto icePysic = node->getPhysicsBody();
        for(int i=0;i<2;i++){
            auto newIce = Sprite::create(StringUtils::format("PNG/5/5/3_%d.png",rand()%4));
            newIce->setPosition(node->getPosition());
            newIce->setRotation(newIce->getRotationX());
            node->getParent()->addChild(newIce,node->getLocalZOrder());
            
            PhysicsBody* box = PhysicsBody::createCircle(newIce->getContentSize().width*0.25f);
            box->setCategoryBitmask(icePysic->getCategoryBitmask());
            box->setCollisionBitmask(icePysic->getCollisionBitmask());
            box->setRotationOffset(newIce->getRotationX());
            newIce->setPhysicsBody(box);
            newIce->runAction(Sequence::create(FadeOut::create(5),CallFunc::create([=](){
                actionNodes.erase(std::find(actionNodes.begin(), actionNodes.end(), newIce));
                newIce->removeFromParent();
            }), nullptr));
            actionNodes.push_back(newIce);
        }
        node->removeFromParent();
    }
}

void BlenderLayer::blendAllEnd(){
    this->stopActionByTag(blendSoundActionTag);
    this->stopPrompt();
    _operate->getNodeByName<ui::Widget*>("btn")->removeAllComponents();
    _operate->getNodeByName<ui::Widget*>("btn")->setEnabled(false);
    SoundPlayer::getInstance()->stopEffectLoop(_loopSound);
    _loopSound = -1;
    auto cup = _operate->getNodeByName("cup");
    CocosHelper::reAddNode(_operate->getNodeByName("lid"), cup);
    auto cupUp = _operate->getNodeByName("cupUp");
    cupUp->setLocalZOrder(15);
    CocosHelper::reAddNode(cupUp, cup);
    cup->getParent()->reorderChild(cup, 10);
 
    cup->runAction(Sequence::create(ScaleTo::create(0.9f, 1.25f),CallFunc::create([=](){
        this->addChild(particleLayer::create(),10);
    }),DelayTime::create(1.5),CallFunc::create([this](){
        
        
        Director::getInstance()->replaceScene(TransitionFade::create(1.2f, FallLayer::createScene(), Color3B::WHITE));
    }), nullptr));
    cup->runAction(JumpTo::create(0.9f, cup->getParent()->convertToNodeSpace(getContentSize()*.5), 200, 1));
}

 void BlenderLayer::onExitTransitionDidStart(){
     BaseMakeLayer::onExitTransitionDidStart();
   
}